// storage/storage.go
package storage

import (
	"context"
	"database/sql"
	"fmt"
	"time"

	"github.com/ev-charging/cloud-platform/config"
	"github.com/go-redis/redis/v8"
)

// Storage 定义统一的存储接口
type Storage interface {
	GetDeviceData(ctx context.Context, deviceID string) (map[string]interface{}, error)
	SaveDeviceData(ctx context.Context, deviceID string, data map[string]interface{}) error
	ListDevices(ctx context.Context) ([]string, error)
	Close() error
}

// NewStorage 根据配置创建存储实例
func NewStorage(cfg *config.StorageConfig) (Storage, error) {
	switch cfg.Type {
	case "redis":
		return newRedisStorage(cfg)
	case "mysql":
		return newMySQLStorage(cfg)
	default:
		return nil, fmt.Errorf("unsupported storage type: %s", cfg.Type)
	}
}

// ================= Redis 实现 =================

type redisStorage struct {
	client *redis.Client
}

func newRedisStorage(cfg *config.StorageConfig) (Storage, error) {
	opt, err := redis.ParseURL(cfg.Redis.Addr)
	if err != nil {
		return nil, err
	}
	if cfg.Redis.Password != "" {
		opt.Password = cfg.Redis.Password
	}
	if cfg.Redis.DB != 0 {
		opt.DB = cfg.Redis.DB
	}

	client := redis.NewClient(opt)

	// Ping
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	if _, err := client.Ping(ctx).Result(); err != nil {
		return nil, fmt.Errorf("failed to connect to redis: %v", err)
	}

	fmt.Println("Redis 连接成功")
	return &redisStorage{client: client}, nil
}

func (r *redisStorage) GetDeviceData(ctx context.Context, deviceID string) (map[string]interface{}, error) {
	// 示例：从 Redis 获取数据
	val, err := r.client.HGetAll(ctx, "device:"+deviceID).Result()
	if err != nil {
		return nil, err
	}
	result := make(map[string]interface{})
	for k, v := range val {
		result[k] = v
	}
	return result, nil
}

func (r *redisStorage) SaveDeviceData(ctx context.Context, deviceID string, data map[string]interface{}) error {
	// 示例：保存到 Redis
	_, err := r.client.HMSet(ctx, "device:"+deviceID, data).Result()
	return err
}

func (r *redisStorage) ListDevices(ctx context.Context) ([]string, error) {
	// 示例：列出所有设备（实际建议使用集合存储）
	keys, err := r.client.Keys(ctx, "device:*").Result()
	if err != nil {
		return nil, err
	}
	return keys, nil
}

func (r *redisStorage) Close() error {
	return r.client.Close()
}

// ================= MySQL 实现 =================

type mysqlStorage struct {
	db *sql.DB
}

func newMySQLStorage(cfg *config.StorageConfig) (Storage, error) {
	db, err := sql.Open("mysql", cfg.MySQL.DSN)
	if err != nil {
		return nil, err
	}
	if err := db.Ping(); err != nil {
		return nil, err
	}
	fmt.Println("MySQL 连接成功")
	return &mysqlStorage{db: db}, nil
}

func (m *mysqlStorage) GetDeviceData(ctx context.Context, deviceID string) (map[string]interface{}, error) {
	// 示例：从数据库中查询
	row := m.db.QueryRowContext(ctx, "SELECT data FROM devices WHERE id = ?", deviceID)
	var data string
	if err := row.Scan(&data); err != nil {
		return nil, err
	}
	return map[string]interface{}{"data": data}, nil
}

func (m *mysqlStorage) SaveDeviceData(ctx context.Context, deviceID string, data map[string]interface{}) error {
	// 示例：保存到数据库
	_, err := m.db.ExecContext(ctx, "INSERT INTO devices (id, data) VALUES (?, ?) ON DUPLICATE KEY UPDATE data = ?",
		deviceID, data["data"], data["data"])
	return err
}

func (m *mysqlStorage) ListDevices(ctx context.Context) ([]string, error) {
	rows, err := m.db.QueryContext(ctx, "SELECT id FROM devices")
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var devices []string
	for rows.Next() {
		var id string
		if err := rows.Scan(&id); err != nil {
			return nil, err
		}
		devices = append(devices, id)
	}
	return devices, nil
}

func (m *mysqlStorage) Close() error {
	return m.db.Close()
}
